// Placed in public domain by Dmitry Olshansky, 2006
package plugins.fr.umlv.ged.toolbox.core;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;

import kiyut.ekspos.BrowserWindow;
import kiyut.ekspos.CmisViewer;
import kiyut.ekspos.WindowManager;
import kiyut.ekspos.prefs.GeneralPreferences;
import kiyut.ekspos.prefs.IIOPreferences;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.flexdock.perspective.PerspectiveManager;
import org.flexdock.view.View;
import org.java.plugin.registry.Extension;
import org.java.plugin.registry.Extension.Parameter;
import org.java.plugin.registry.ExtensionPoint;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.util.ExtendedProperties;

import com.jgoodies.looks.LookUtils;
import com.jgoodies.looks.Options;
import com.jgoodies.looks.plastic.PlasticLookAndFeel;
import com.jgoodies.looks.plastic.theme.ExperienceBlue;

import fr.umlv.authentication.Connection;
import fr.umlv.authentication.SessionHandler;
import fr.umlv.cmis.gedconfig.GEDDockingPersistence;
import fr.umlv.main.Application;
import fr.umlv.main.ApplicationPlugin;
import fr.umlv.main.SplashScreen;


// TODO: Auto-generated Javadoc
/**
 * The Class CorePlugin.
 */
public final class CorePlugin extends ApplicationPlugin implements Application {
	
	/** The Constant PLUGIN_ID. */
	public static final String PLUGIN_ID = "org.jpf.demo.toolbox.core";

	/** The data folder. */
	private File dataFolder;
	//private JFrame frame;
	/** The frame. */
	private BrowserWindow frame;


	/** The login. */
	@SuppressWarnings("unused")
	private Connection login;

	/**
	 * Gets the data folder.
	 *
	 * @param descr the descr
	 * @return the data folder
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public File getDataFolder(final PluginDescriptor descr) throws IOException {
		File result = new File(dataFolder, descr.getId());
		if (!result.isDirectory() && !result.mkdirs()) {
			throw new IOException("can't create data folder " + result
					+ " for plug-in " + descr.getId());
		}
		return result;
	}

	/**
	 * Gets the frame.
	 *
	 * @return the frame
	 */
	public BrowserWindow getFrame() {
		return frame;
	}

	/* (non-Javadoc)
	 * @see org.java.plugin.Plugin#doStart()
	 */
	@Override
	protected void doStart() throws Exception {
		// no-op
	}

	/* (non-Javadoc)
	 * @see org.java.plugin.Plugin#doStop()
	 */
	@Override
	protected void doStop() throws Exception {
		// no-op
	}

	/* (non-Javadoc)
	 * @see fr.umlv.main.ApplicationPlugin#initApplication(org.java.plugin.util.ExtendedProperties, java.lang.String[])
	 */
	@Override
	protected Application initApplication(final ExtendedProperties config,
			final String[] args) throws Exception {
		dataFolder = new File(config.getProperty("dataFolder",
				"." + File.separator + "data"));
		dataFolder = dataFolder.getCanonicalFile();
		log.debug("data folder - " + dataFolder);
		if (!dataFolder.isDirectory() && !dataFolder.mkdirs()) {
			throw new Exception("data folder " + dataFolder + " not found");
		}
		return this;
	}

	/* (non-Javadoc)
	 * @see fr.umlv.main.Application#startApplication()
	 */
	public void startApplication() {

		initialize();

		Connection login = new Connection(this);
		login.setSize(500,300);
		login.setLocationRelativeTo(login.getParent());
		login.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		login.setVisible(true);

		try {
			while(SessionHandler.getClientSession()==null || SessionHandler.getLocale()==null){
				synchronized (this) {
					this.wait();
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});
	}

	/**
	 * Creates the and show gui.
	 */
	protected void createAndShowGUI() {

		frame = BrowserWindow.getInstance();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		frame.setIconImage(new ImageIcon(getClass()
				.getResource("sabre.png").getPath()).getImage());

		WindowManager.createInstance(frame);

		// setup the PerspectiveManager
		GEDDockingPersistence dp = new GEDDockingPersistence();
		PerspectiveManager.setPersistenceHandler(dp);
		frame.restoreDocking(); 

		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosed(WindowEvent evt) {
				System.exit(0);
			}
		});

		frame.setViewer(new CmisViewer() {
			public void view(List<CmisObject> files, int index) {
				WindowManager.getInstance().openViewerWindow(files, index);
			}
		});

		ExtensionPoint toolExtPoint =
			getManager().getRegistry().getExtensionPoint(
					getDescriptor().getId(), "Tool");


		JMenu menuTool = null;

		for(int i=0;i<frame.getJMenuBar().getMenuCount();i++){

			if("Tools".equals(frame.getJMenuBar().getMenu(i).getText()) || "Outils".equals(frame.getJMenuBar().getMenu(i).getText())){
				menuTool = frame.getJMenuBar().getMenu(i);
			}
		}

		int number = 1;

		for (Extension ext : toolExtPoint.getConnectedExtensions()) {
			JPanel panel = new JPanel();
			panel.putClientProperty("extension", ext);
			Parameter iconParam = ext.getParameter("icon");
			@SuppressWarnings("unused")
			URL iconUrl = null;
			if (iconParam != null) {
				iconUrl = getManager().getPluginClassLoader(
						ext.getDeclaringPluginDescriptor())
						.getResource(iconParam.valueAsString());
			}

			// Test a ameliorer
			String id = "_plugin_ged_"+number+".view";
			activateTool(panel,menuTool);	
			if(panel.getComponentCount()!=0){
				frame.mgr.getCurrentPerspective().getInitialSequence(). add(id,BrowserWindow.DOCKING_LIST_VIEW);
				frame.mgr.reset();
				View v = frame.mapViewPlugins.get(id);

				View v2 = frame.mapViewPlugins.get("folders_and_files_docking");
				if(v2.getTitlebar() != null){	
					v2.setTitlebar(null);
				}

				if(v!=null){
					v.setTitle(ext.getParameter("name").valueAsString());
					v.setName(ext.getParameter("name").valueAsString());
					v.setTabText(ext.getParameter("name").valueAsString());
					v.getContentPane().add(panel);
				}
			}
			number++;

		}

		View v3 = frame.mapViewPlugins.get("folders_and_files_docking");
		if(v3!= null){

			if(v3.getParent() instanceof JTabbedPane){
				JTabbedPane tabbedPane = (JTabbedPane)v3.getParent();
				tabbedPane.setSelectedIndex(0);
				tabbedPane.setTabPlacement(JTabbedPane.TOP);
			}
		}
		
		v3 = frame.mapViewPlugins.get(BrowserWindow.DOCKING_TREE_VIEW);
		if(v3!= null){
			JTabbedPane tabbedPane = (JTabbedPane)v3.getParent();
			tabbedPane.setSelectedIndex(0);
			tabbedPane.setTabPlacement(JTabbedPane.TOP);
		}

		SplashScreen.getInstance().hideSplashScreen();
		
		frame.setVisible(true);

	}

	/*
	 * This method activates (initializes Tool) if it wasn't activated yet.
	 */
	/**
	 * Activate tool.
	 *
	 * @param toolComponent the tool component
	 * @param menu the menu
	 */
	protected void activateTool(final JComponent toolComponent,JMenu menu) {
		Extension ext =
			(Extension) toolComponent.getClientProperty("extension");

		Tool tool = (Tool) toolComponent.getClientProperty("toolInstance");
		if (tool == null) {
			try {
				// Activate plug-in that declares extension.
				getManager().activatePlugin(
						ext.getDeclaringPluginDescriptor().getId());
				// Get plug-in class loader.
				ClassLoader classLoader = getManager().getPluginClassLoader(
						ext.getDeclaringPluginDescriptor());
				// Load Tool class.
				Class<?> toolCls = classLoader.loadClass(
						ext.getParameter("class").valueAsString());
				// Create Tool instance.
				tool = (Tool) toolCls.newInstance();
				// Initialize class instance according to interface contract.
				tool.setLanguage(SessionHandler.getLocale());
				tool.init(toolComponent);

				// Add the plugin menu
				JMenuItem menuTool = tool.getMenu();
				if(menuTool!=null)
					menu.add(menuTool);

				// Add a toolbar button
				if(tool.getActionToolBar()!=null)
					frame.getToolBar().add(tool.getActionToolBar());

				// Add a menu in the popup menu for document
				if(tool.createPopUpMenuDocument())
					frame.getShellListViewPopupMenu().add(tool.getActionPopUpMenu());

				// Add a menu in the popup menu for folder
				if(tool.createPopUpMenuFolder())
					frame.getShellListViewPopupMenuFolder().add(tool.getActionPopUpMenu());

				frame.getShellListView().addListSelectionListener(tool);
				frame.getShellListView().addListDataListener(tool);

			} catch (Throwable t) {
				toolComponent.setLayout(new BorderLayout());
				toolComponent.add(new JLabel(t.toString()), BorderLayout.NORTH);
				JScrollPane scrollPane = new JScrollPane();
				toolComponent.add(scrollPane, BorderLayout.CENTER);
				StringBuffer sb = new StringBuffer();
				String nl = System.getProperty("line.separator");
				Throwable err = t;
				while (err != null) {
					if (err != t) {
						sb.append(nl).append("Caused by " + err).append(nl).append(nl);
					}
					StackTraceElement[] stackTrace = err.getStackTrace();
					for (int i = 0; i < stackTrace.length; i++) {
						sb.append(stackTrace[i].toString()).append(nl);
					}
					err = err.getCause();
				}
				JTextArea textArea = new JTextArea(sb.toString());
				textArea.setBackground(java.awt.SystemColor.control);
				textArea.setEditable(false);
				scrollPane.setViewportView(textArea);
				textArea.setCaretPosition(0);
				return;
			}
			toolComponent.putClientProperty("toolInstance", tool);
		}
	}

	/**
	 * Save state.
	 */
	protected void saveState() {
		Properties props = new Properties();
		props.setProperty("window.X", "" + frame.getX());
		props.setProperty("window.Y", "" + frame.getY());
		props.setProperty("window.width", "" + frame.getWidth());
		props.setProperty("window.height", "" + frame.getHeight());
	}

	/**
	 * Initialize.
	 */
	private void initialize() {
		String osName = System.getProperty("os.name").toUpperCase();

		// set default swing bold to false, only for JVM 1.5 or above
		UIManager.put("swing.boldMetal", Boolean.FALSE);
		
		// set LaF
		LookAndFeel lnf = UIManager.getLookAndFeel();
		if (lnf != null && lnf.getID().equalsIgnoreCase("Metal")) {
			String lnfClassName = null;
			if (osName.startsWith("MAC")) {
				System.setProperty("com.apple.mrj.application.apple.menu.about.name", kiyut.ekspos.Application.getName());
				System.setProperty("apple.laf.useScreenMenuBar","true");
				lnfClassName = UIManager.getSystemLookAndFeelClassName();
			} else if (osName.startsWith("WINDOWS")) {
				UIManager.put("ClassLoader", LookUtils.class.getClassLoader());
				lnfClassName = UIManager.getSystemLookAndFeelClassName();
			} else if (osName.startsWith("LINUX")) {
				UIManager.put("ClassLoader", LookUtils.class.getClassLoader());
				lnfClassName = UIManager.getSystemLookAndFeelClassName();
			} else {
				UIManager.put("ClassLoader", LookUtils.class.getClassLoader());
				lnfClassName = Options.getCrossPlatformLookAndFeelClassName();
				PlasticLookAndFeel.setTabStyle(PlasticLookAndFeel.TAB_STYLE_METAL_VALUE);
				PlasticLookAndFeel.setPlasticTheme(new ExperienceBlue());
				Options.setUseNarrowButtons(false);
			}

			if (lnfClassName != null) {
				try {
					UIManager.setLookAndFeel(lnfClassName);
				} catch (Exception ex) {
					System.err.println("Unable to set LookAndFeel, use default LookAndFeel.\n" + ex.getMessage());
				}
			}
		}

		// initialize preferences.
		GeneralPreferences.getInstance();
		IIOPreferences.getInstance();
	}
}
